package com.ruge.tool.videoCapture;

import com.ruge.tool.id.IdTool;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.*;
import org.bytedeco.opencv.global.opencv_core;
import org.bytedeco.opencv.opencv_core.IplImage;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

/**
 * description
 * create Time at 2022/6/20 15:39
 *
 * @author alice.ruge
 * @since 0.0.7
 */
@Slf4j
public class VideoCaptureTool {
    /**
     * 默认图片格式 jpg
     */
    public static String DEFAULT_IMG_FORMAT = "jpg";
    /**
     * 图片格式 png
     */
    public static String IMG_FORMAT_PNG = "png";
    /**
     * /*图片格式 jpg
     */
    public static String IMG_FORMAT_JPG = "jpg";
    /**
     * 第一帧
     */
    public final static int FIRST = 0;
    /**
     * 最后一帧
     */
    public final static int LAST = Integer.MAX_VALUE;

    /**
     * 获取视频时长，单位为秒 * * @param video 源视频文件 * @return 时长（s）
     */
    public static long getVideoDuration(File video) {
        long duration = 0L;
        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(video);
        try {
            ff.start();
            duration = ff.getLengthInTime() / (1000 * 1000);
            ff.stop();
        } catch (FrameGrabber.Exception e) {
            e.printStackTrace();
        }
        return duration;
    }

    /**
     * 截取视频得到指定帧的图片
     *
     * @param video   源视频文件
     * @param picPath 截图存放路径
     */
    @SneakyThrows
    public static void getVideoPic(File video, String picPath) {
        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(video);
        try {
            ff.start(); // 截取中间帧图片(具体依实际状况而定)
            int i = 0;
            int length = ff.getLengthInFrames();
            int middleFrame = length / 2;
            Frame frame = null;
            while (i < length) {
                frame = ff.grabFrame();
                if ((i > middleFrame) && (frame.image != null)) {
                    break;
                }
                i++;
            }
            // 截取的帧图片
            Java2DFrameConverter converter = new Java2DFrameConverter();
            BufferedImage srcImage = converter.getBufferedImage(frame);
            int srcImageWidth = srcImage.getWidth();
            int srcImageHeight = srcImage.getHeight();
            // 对截图进行等比例缩放(缩略图)
            int width = 480;
            int height = (int) (((double) width / srcImageWidth) * srcImageHeight);
            BufferedImage thumbnailImage = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
            thumbnailImage.getGraphics().drawImage(srcImage.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
            File picFile = new File(picPath);
            ImageIO.write(thumbnailImage, "jpg", picFile);
            ff.stop();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取指定视频的帧并保存为图片至指定目录
     *
     * @param filePath       视频路径
     * @param targerFilePath 第一帧图片存储位置
     * @param targetFileName 图片名称
     * @param index          指定帧数
     * @throws Exception {@link Exception}
     */

    public static void GetVideoGainImg(String filePath, String targerFilePath, String targetFileName, Integer index)
            throws Exception {

        FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
        ff.start();
        // 获取视频总帧数
        int ftp = ff.getLengthInFrames();
        // 视频旋转角度，可能是null
        String rotate = ff.getVideoMetadata("rotate");
        System.out.println("时长 " + ftp / ff.getFrameRate() / 60);
        Frame frame;
        int flag = 3;
        while (flag <= ftp) {
            //获取帧
            frame = ff.grabImage();
            if (null == index || flag == index) {
                if (null != rotate && rotate.length() > 1) {
                    OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
                    IplImage src = converter.convert(frame);
                    frame = converter.convert(rotate(src, Integer.parseInt(rotate)));
                }
                doExecuteFrame(frame, targerFilePath, targetFileName);
            }
            flag++;
        }
        ff.stop();
    }

    /**
     * 旋转角度的。这个是为了保证截取到的图和视频中的旋转信息一致
     *
     * @param src   图片路径
     * @param angle 旋转角度
     * @return 旋转后的文件
     */
    public static IplImage rotate(IplImage src, int angle) {
        IplImage img = IplImage.create(src.height(), src.width(), src.depth(), src.nChannels());
        opencv_core.cvTranspose(src, img);
        opencv_core.cvFlip(img, img, angle);
        return img;
    }

    public static void doExecuteFrame(Frame frame, String targetFilePath, String targetFileName) {
        if (null == frame || null == frame.image) {
            return;
        }
        //创建BufferedImage对象
        Java2DFrameConverter converter = new Java2DFrameConverter();
        String imageMat = "jpg";
        String fileName = targetFilePath + File.separator + targetFileName + IdTool.randomUUID() + "." + imageMat;
        BufferedImage bufferedImage = converter.getBufferedImage(frame);
        File output = new File(fileName);
        try {
            ImageIO.write(bufferedImage, imageMat, output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        String url = "https://avris-uat-1256532032.cos.ap-beijing.myqcloud.com/cms-static/avris/9c38da1bcf4641d5bc9e47dbb2ff6aef.mp4";
        GetVideoGainImg(url, "E:\\data\\tmp", "first", 20);
    }
}
